bugfix(rallypoint): Make healed units follow building rally point on exit#1822
bugfix(rallypoint): Make healed units follow building rally point on exit#1822xezon merged 3 commits intoTheSuperHackers:mainfrom
Conversation
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
610b09f to
8fe5984
Compare
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp | Refactors exitObjectViaDoor to use getRallyPoint() instead of checking m_rallyPointExists directly; adds a #if !RETAIL_COMPATIBLE_CRC-guarded fallback in getRallyPoint() to delegate to the primary exit interface's rally point, enabling HealContain to propagate the building's rally point. Self-recursion guard (primaryExit != this) is correct. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp | Adds #if !RETAIL_COMPATIBLE_CRC-guarded rally point move after healing is complete and takeoff begins. The pattern follows established aiDoCommand pending-command mechanics: calling aiMoveToPosition while m_flightStatus != CHINOOK_FLYING causes aiDoCommand to store the command and set m_hasPendingCommand = true, dispatched when the Chinook becomes idle post-takeoff. Note: aiDoCommand also clears m_airfieldForHealing (to INVALID_ID) via the non-evacuate path, but pp->setHealee(false) was already called so this is benign. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp | Adds #if !RETAIL_COMPATIBLE_CRC-guarded rally point move after helipad-produced aircraft finish healing. Since friend_setAllowAirLoco(true) and setState(TAKING_OFF_AWAIT_CLEARANCE) are called first (setting TAKEOFF_IN_PROGRESS = true via onEnter), the subsequent aiMoveToPosition correctly routes through the TAKEOFF_IN_PROGRESS guard in aiDoCommand, storing the command as pending for dispatch after takeoff completes. The same-frame else if (HAS_PENDING_COMMAND) re-dispatch re-queues the command safely. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp | Mirror of the Generals/ counterpart — identical changes applied correctly to the Zero Hour codebase. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp | Mirror of the Generals/ counterpart — identical healing rally point logic applied to the Zero Hour Chinook. Same behavioral analysis applies. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp | Mirror of the Generals/ counterpart — identical healing rally point logic applied to the Zero Hour jet/helicopter. Same behavioral analysis applies. |
Sequence Diagram
sequenceDiagram
participant Update as ChinookAIUpdate / JetAIUpdate
participant SM as StateMachine
participant PP as ParkingPlace
participant AI as AIInterface
participant Exit as ExitInterface (Airfield)
Update->>PP: setHealee(unit, false)
Update->>SM: setState(TAKING_OFF / TAKING_OFF_AWAIT_CLEARANCE)
Note over SM: onEnter() sets TAKEOFF_IN_PROGRESS=true
Update->>Exit: getRallyPoint()
Exit-->>Update: Coord3D* rallyPoint (if set)
Update->>AI: aiMoveToPosition(rallyPoint)
AI->>AI: aiDoCommand(AICMD_MOVE_TO_POSITION)
Note over AI: TAKEOFF_IN_PROGRESS=true →<br/>store as m_mostRecentCommand,<br/>set HAS_PENDING_COMMAND=true, return
Note over SM: Takeoff animation completes,<br/>TAKEOFF_IN_PROGRESS=false
SM-->>Update: unit is now idle (flying)
Update->>AI: dispatch m_mostRecentCommand (move to rally)
AI->>AI: aiDoCommand(AICMD_MOVE_TO_POSITION)
Note over AI: ALLOW_AIR_LOCO=true, not landing/takeoff →<br/>AIUpdateInterface::aiDoCommand executes move
Last reviewed commit: 7c656b2
8fe5984 to
faf8a09
Compare
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
faf8a09 to
4e9ef5f
Compare
4e9ef5f to
e87b99b
Compare
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Outdated
Show resolved
Hide resolved
Additional Comments (2)
Prompt To Fix With AIThis is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Line: 1038:1039
Comment:
`airfield` could be `nullptr` if the airfield was destroyed or doesn't exist. Need null check before calling `getObjectExitInterface()`.
```suggestion
Object *airfield = TheGameLogic->findObjectByID( m_airfieldForHealing );
if (airfield)
{
const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
if( rp )
{
AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
parms.m_pos = *rp;
m_pendingCommand.store( parms );
m_hasPendingCommand = true;
}
}
```
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Line: 1782:1783
Comment:
`airfield` could be `nullptr` if the airfield was destroyed or doesn't exist (see line 1717-1718 in same file for precedent). Need null check before calling `getObjectExitInterface()`.
```suggestion
Object *airfield = TheGameLogic->findObjectByID( jet->getProducerID() );
if (airfield)
{
const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
if( rp )
{
AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
parms.m_pos = *rp;
m_mostRecentCommand.store( parms );
setFlag(HAS_PENDING_COMMAND, true);
}
}
```
How can I resolve this? If you propose a fix, please make it concise. |
e87b99b to
ffa98ad
Compare
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HealContain.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Outdated
Show resolved
Hide resolved
ffa98ad to
e4eac2e
Compare
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
2c1be60 to
5a3b849
Compare
xezon
left a comment
There was a problem hiding this comment.
Can you explain the difference between the waypointing in OpenContain and in ChinookAIUpdate? Which one is used in what event?
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
War factory repair is unrelated - it uses the dock system ( |
5a3b849 to
c1204d1
Compare
c1204d1 to
7c656b2
Compare
Units will now follow building rally point after healing.
Closes #221
Behavior after change:
2026-03-14T143000_FFB.mp4